package org.budo.filestore.fastdfs;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

import org.budo.filestore.api.DeleteResponse;
import org.budo.filestore.api.DownloadRequest;
import org.budo.filestore.api.FileMeta;
import org.budo.filestore.api.UploadRequest;
import org.budo.filestore.api.UploadResponse;
import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.StringUtil;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.FileInfo;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author limingwei
 */
public class FastdfsFileStore extends AbstractFastdfsFileStore {
    private static final Logger log = LoggerFactory.getLogger(FastdfsFileStore.class);

    @Override
    public String uploadToken(UploadRequest request) {
        throw new UnsupportedOperationException();
    }

    @Override
    public UploadResponse upload(UploadRequest request) {
        try {
            StorageClient storageClient = this.getStorageClient();

            byte[] file_buff = IoUtil.toByteArray(request.getInputStream());
            String file_ext_name = this.getFileExtName(request.getContentUrl());
            NameValuePair[] meta_list = new NameValuePair[0];

            // results[0]: the group name to store the file
            // results[1]: the new created filename // M00/00/00/wKgRcFV_08OAK_KCAAAA5fm_sy874.conf
            String[] results = storageClient.upload_file(this.getGroupName(), file_buff, file_ext_name, meta_list);
            log.info("#47 upload_file return " + Arrays.toString(results));

            return new FastdfsUploadResponse(results[0],results[1]);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public InputStream downloadStream(DownloadRequest request) {
        try {
            StorageClient storageClient = this.getStorageClient();

            String remote_filename = request.getContentUrl();
            byte[] bytes = storageClient.download_file(this.getGroupName(), remote_filename);

            return new ByteArrayInputStream(bytes);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public FileMeta getFileMeta(DownloadRequest request) {
        try {
            StorageClient storageClient = this.getStorageClient();

            String remote_filename = request.getContentUrl();
            FileInfo fileInfo = storageClient.get_file_info(this.getGroupName(), remote_filename);

            log.info("#89 getFileMeta return " + fileInfo);

            return null;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public DeleteResponse delete(DownloadRequest request) {
        try {
            StorageClient storageClient = this.getStorageClient();

            String remote_filename = request.getContentUrl();
            int delete_file = storageClient.delete_file(this.getGroupName(), remote_filename);

            log.info("#89 delete return " + delete_file);

            return null;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    private StorageClient getStorageClient() throws IOException {
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        StorageServer storageServer = null;

        return new StorageClient(trackerServer, storageServer);
    }

    @Override
    public String downloadUrl(DownloadRequest request) {
        throw new UnsupportedOperationException();
    }

    /**
     * 文件扩展名
     */
    private String getFileExtName(String contentUrl) {
        if (StringUtil.isEmpty(contentUrl)) {
            return "null";
        }

        int i = contentUrl.lastIndexOf('.');
        if (i < 0) {
            return "nodot";
        }
        if (i >= contentUrl.length() - 1) {
            return "endwithdot";
        }

        return contentUrl.substring(i + 1);
    }
}
